#ifndef __FIBER_FIBER_H__
#define __FIBER_FIBER_H__

#include <stdio.h>        // 标准输入输出
#include <ucontext.h>     // 上下文管理（保存/恢复线程状态，用于协程切换）
#include <functional>     // 函数对象（存储协程回调）
#include <iostream>       // 标准输入输出流
#include <memory>         // 智能指针（管理协程生命周期）

namespace fiber {

/**
 * @brief 协程类：封装用户态协程的创建、切换、状态管理等功能
 * 继承std::enable_shared_from_this<Fiber>：允许协程对象生成自身的shared_ptr，方便在回调中安全引用
 */
class Fiber : public std::enable_shared_from_this<Fiber> {
public:
    // 协程智能指针类型（用于安全管理协程生命周期）
    using ptr = std::shared_ptr<Fiber>;

    /**
     * @brief 协程状态枚举（状态机）
     * 协程的生命周期通过状态转换管理
     */
    enum class State {
        READY,   // 就绪态：刚创建或调用yield()后，等待被resume()唤醒
        RUNNING, // 运行态：调用resume()后，正在执行的状态
        TERM     // 结束态：协程回调函数执行完毕后的状态
    };

private:
    /**
     * @brief 私有构造函数：初始化当前线程的 主协程
     * 主协程是线程启动时默认的协程，负责调度其他子协程
     * 仅在当前线程首次获取协程（GetThis()）时调用
     */
    Fiber();

public:
    /**
     * @brief 公有构造函数：创建子协程
     * @param cb 协程执行的回调函数（协程的核心逻辑）
     * @param stackSz 协程栈大小（0表示使用默认大小）
     * @param run_in_scheduler 该协程是否由调度器管理（true：参与调度；false：手动管理）
     */
    Fiber(std::function<void()> cb, size_t stackSz = 0, bool run_in_scheduler = true);

    /**
     * @brief 析构函数：释放协程资源（主要是栈空间）
     */
    ~Fiber();

    /**
     * @brief 重置协程：复用已结束的协程栈空间，重新设置回调函数
     * @param cb 新的回调函数
     * 作用：避免重复分配栈空间，提高效率（栈空间分配成本较高）
     */
    void reset(std::function<void()> cb);

    /**
     * @brief 恢复协程执行（从就绪态切换到运行态）
     * 逻辑：保存当前运行协程的上下文，切换到本协程的上下文并执行
     */
    void resume();

    /**
     * @brief 让出协程执行权（从运行态切换到就绪态）
     * 逻辑：保存本协程的上下文，切换回主协程或调度器协程的上下文
     */
    void yield();

    /**
     * @brief 获取协程ID
     * @return 协程唯一标识ID
     */
    uint64_t getId() const { return m_id; }

    /**
     * @brief 获取协程当前状态
     * @return 协程状态（READY/RUNNING/TERM）
     */
    State getState() const { return m_state; }

    /**
     * @brief 静态方法：设置当前正在运行的协程
     * @param f 当前运行的协程指针
     * 作用：在线程局部存储中记录当前活跃协程，方便后续获取
     */
    static void SetThis(Fiber *f);

    /**
     * @brief 静态方法：获取当前线程中正在执行的协程
     * @return 当前协程的智能指针
     * 逻辑：若线程未初始化协程，会创建主协程（线程默认协程）
     */
    static Fiber::ptr GetThis();

    /**
     * @brief 静态方法：获取系统中创建的协程总数
     * @return 协程总数（全局计数）
     */
    static uint64_t TotalFiberNum();

    /**
     * @brief 静态方法：协程的入口函数
     * 作用：封装协程回调的执行，执行完毕后自动切换状态并让出执行权
     */
    static void MainFunc();

    /**
     * @brief 静态方法：获取当前正在运行的协程ID
     * @return 当前协程ID
     */
    static uint64_t GetCurFiberID();

private:
    uint64_t m_id = 0;               // 协程唯一ID（全局递增分配）
    uint32_t m_stackSize = 0;        // 协程栈大小（字节）
    State m_state = State::READY;    // 协程当前状态（默认就绪态）
    ucontext_t m_ctx;                // 协程上下文（保存寄存器、栈指针等执行状态）
    void* m_stack_ptr = nullptr;     // 协程栈内存的起始地址（动态分配的栈空间）
    std::function<void()> m_cb;      // 协程执行的回调函数（核心逻辑）
    bool m_isRunInScheduler;         // 是否由调度器管理（true：由Scheduler调度；false：手动控制）
};

}  // namespace fiber

#endif  // __FIBER_FIBER_H__